﻿using System;
using System.Linq;
using System.Collections.Generic;
using LinqKit;

using Syncfusion.Windows.Forms.Chart;

using PMngr.Data;

namespace PMngr.Main
{
    public partial class PieChart : BaseControl, IControl
    {
        private IRepositoryFactory repositoryFactory;
        private IDictionary<int, string> _axesLabel;

        public PieChart()
        {
            InitializeComponent();
        }

        public PieChart(IRepositoryFactory repositoryFactory)
            : this()
        {
            this.repositoryFactory = repositoryFactory;
        }

        private void InitializeUnitTypeData()
        {
            var predicate = PredicateBuilder.True<Unit>();
            predicate = predicate.And(u => u.IsValid && u.ParentUnit == null);

            using (var repository = repositoryFactory.CreateRepository())
            {
                var datasource = repository.Find<Unit>(predicate.Expand()).GroupBy(u => u.UnitType);

                var result = datasource.ToList();
                ChartSeries series = new ChartSeries("UnitType");
                for (var i = 0; i < result.Count; i++)
                {
                    ChartPoint point = new ChartPoint(i, result[i].Count());
                    series.Points.Add(point);

                    series.Styles[i].Text = String.Format("{0}: {1}", result[i].Key.Name, result[i].Count());
                }
                series.Type = ChartSeriesType.Pie;
                this.chart.Series.Clear();
                this.chart.Series.Add(series);

                for (int i = 0; i < series.Points.Count; i++)
                    series.Styles[i].Border.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
                //
                series.ConfigItems.PieItem.LabelStyle = ChartAccumulationLabelStyle.OutsideInColumn;
                series.Style.DisplayText = true;
                series.Style.Font.Size = 9.0f;
                series.ConfigItems.PieItem.AngleOffset = 60;
            }
            this.chart.Series[0].ShowTicks = true;
            this.chart.Series[0].ExplodedAll = true;
            this.chart.Series[0].ExplosionOffset = 9f;
            //
            ChartAppearance.ApplyChartStyles(this.chart, "单位区域");
        }

        private void InitializeUnitKindData()
        {
            var predicate = PredicateBuilder.True<Unit>();
            predicate = predicate.And(u => u.IsValid && u.ParentUnit != null);

            using (var repository = repositoryFactory.CreateRepository())
            {
                var datasource = repository.Find<Unit>(predicate.Expand()).GroupBy(u => u.UnitType);

                var result = datasource.ToList();
                ChartSeries series = new ChartSeries("UnitKind");
                for (var i = 0; i < result.Count; i++)
                {
                    ChartPoint point = new ChartPoint(i, result[i].Count());
                    series.Points.Add(point);

                    series.Styles[i].Text = String.Format("{0}: {1}", result[i].Key.Name, result[i].Count());
                }
                series.Type = ChartSeriesType.Pie;
                this.chartUnitKind.Series.Clear();
                this.chartUnitKind.Series.Add(series);

                for (int i = 0; i < series.Points.Count; i++)
                    series.Styles[i].Border.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
                //
                series.ConfigItems.PieItem.LabelStyle = ChartAccumulationLabelStyle.OutsideInColumn;
                series.Style.DisplayText = true;

                series.Style.Font.Size = 9.0f;
                series.ConfigItems.PieItem.AngleOffset = 60;
            }

            this.chartUnitKind.Series[0].ShowTicks = true;
            this.chartUnitKind.Series[0].ExplodedAll = true;
            this.chartUnitKind.Series[0].ExplosionOffset = 9f;
            //
            ChartAppearance.ApplyChartStyles(this.chartUnitKind, "单位性质");          
        }

        private int GetQuantity(int unitType, int unitKind)
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                var datasource =
                    repository.Find<Unit>(u => u.UnitType.Code == unitKind && u.ParentUnit.UnitType.Code == unitType);
                var result = datasource.Count();
                return result;
            }
        }

        protected void InitializeColumnChartData()
        {
            this.chartColumn.Series.Clear();
            _axesLabel = new Dictionary<int, string>();

            using (var repository = repositoryFactory.CreateRepository())
            {
                var unitTypes =
                    repository.Find<ItemBase>(i => i.Type == "UnitType" && i.IsValid).OrderBy(i => i.Order).ToList();
                var unitKinds =
                    repository.Find<ItemBase>(i => i.Type == "UnitKind" && i.IsValid).OrderBy(i => i.Order).ToList();

                for (var i = 0; i < unitTypes.Count; i++)
                    _axesLabel.Add(i, unitTypes[i].Name);

                for (var i = 0; i < unitKinds.Count; i++)
                {
                    ChartSeries series = new ChartSeries(unitKinds[i].Name);
                    series.Type = ChartSeriesType.Column;
                    series.Text = unitKinds[i].Name;

                    for (var j = 0; j < unitTypes.Count; j++)
                    {
                        var count = GetQuantity(unitTypes[j].Code, unitKinds[i].Code);
                        ChartPoint point = new ChartPoint(j + 2, count);
                        series.Points.Add(point);
                    }

                    this.chartColumn.Series.Add(series);
                }

                ColumnAppearance.ApplyChartStyles(this.chartColumn, unitTypes.Count);
            }
        }

        public override void InitializeControls()
        {
            // 单位区域分类
            InitializeUnitTypeData();
            // 单位性质分类
            InitializeUnitKindData();
            //
            InitializeColumnChartData();
            //
            this.chartColumn.ChartFormatAxisLabel += new ChartFormatAxisLabelEventHandler(this.chartColumn_ChartFormatAxisLabel);              
        }

        private void chartColumn_ChartFormatAxisLabel(object sender, ChartFormatAxisLabelEventArgs e)
        {
            if (e.AxisOrientation == ChartOrientation.Horizontal)
            {
                int value = (int)e.Value - 2;
                if (_axesLabel.ContainsKey(value))
                    e.Label = _axesLabel[value];
                else
                    e.Label = String.Empty;

                e.Handled = true;
            }
        }
    }
}
